package org.goobs.chess;

import org.goobs.chess.ChessPosition.PositionInformation;


public class ComputerChessAgent implements ChessAgent{

	private static final int depth = 2;
	
	private int color;
	private boolean won;
	
	private ChessPosition searchResult;
	private int searchCalls;
	
	public ComputerChessAgent(int color){
		this.color = color;
		this.won = false;
	}
	
	private final int opponentColor(){
		return opponentColor(color);
	}
	
	private int heuristic(PositionInformation info){
		//--Points
		//(actual point difference)
		int pointDif = info.getPoints(color) - info.getPoints(opponentColor());
		//(take-able points)
		int takablePoints = info.getTakablePoints();
		int points = pointDif + takablePoints;
		
		
		return points;
	}
	
	private int minimax(ChessPosition pos, int depthToGo){
		searchCalls = 0;
		return minimax(pos, depthToGo, color, true);
	}
	
	private int minimax(ChessPosition pos, int depthToGo, int turn, boolean firstTime){
		searchCalls++;
		//--Base Case 1: maximum depth
		if(turn == color){
			depthToGo--;
			if(depthToGo < 0){
				return heuristic(pos.calculateInformation(turn));
			}
		}
		
		//--Recursive case
		//(set base for max/min)
		int score;
		if(turn == color){
			score = Integer.MIN_VALUE;
		}else{
			score = Integer.MAX_VALUE;
		}
		PositionInformation info = pos.calculateInformation(turn);
		//(base case 2: check mate)
		if(info.getChildren().size() == 0){
			return score;	//-inf if our turn, inf if other's turn
		}
		//(iterate through the children)
		for(ChessPosition child : info.getChildren()){
			int recScore = minimax(child, depthToGo, opponentColor(turn), false);
			if( (   (turn == color) && (recScore > score)   ) ||
				(   (turn != color) && (recScore < score)   ) ){
				score = recScore;
				if(firstTime){
					System.out.println(toColor(turn) + ": best score so far: " + score + " (" 
							+ ChessPosition.subtract(pos, child) + ")");
					searchResult = child;
				}
			}
		}
		
		//--Return
		return score;
	}
	
	
	
	@Override
	public ChessMove decideMove(ChessPosition pos) {
		System.out.println("position evaluation: " + heuristic(pos.calculateInformation(color)));
		int maxScore = minimax(pos, depth);
		System.out.println("total search calls: " + searchCalls);
		System.out.println("minimax score: " + maxScore);
		
//		//--Backtrace
//		//(initialize stuff)
//		ChessPosition trace = searchResult;
//		int turn = opponentColor();
//		System.out.println("     -----Backtrace------     ");
//		System.out.println("---" + toColor(color) + "---");
//		searchResult.printToConsole();
//		int d = depth-1;
//		//(recursive)
//		while(d >= 0){
//			System.out.println("---" + toColor(turn) + "---");
//			//(run stuff)
//			int score = minimax(trace, d, turn, true);
//			if(turn == color){
//				d--;
//			}
//			turn = opponentColor(turn);
//			trace = searchResult;
//			//(print stuff)
//			System.out.println(">>" + score);
//			trace.printToConsole();
//			System.out.println();
//		}
//		System.out.println();
		
		return ChessPosition.subtract(pos, searchResult);
	}

	@Override
	public int getColor() {
		return color;
	}

	@Override
	public boolean claimsVictory() {
		return won;
	}
	
	private static final int opponentColor(int color){
		return (color+1)%2;
	}
	
	private static final String toColor(int color){
		if(color == WHITE){
			return "WHITE";
		}else{
			return "BLACK";
		}
	}

}
